package com.spleeb.pixelengine;

import java.util.ArrayList;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class GameView extends SurfaceView implements SurfaceHolder.Callback,Screen{
	public int[] psz = new int[]{240,160};
	public int[] pixels = new int[psz[0]*psz[1]];
	public ArrayList<ScreenObject> game_objects;
	public ArrayList<ScreenObject> hud_objects;
	public Matrix camera_matrix = new Matrix();
	public Satrix cam = new Satrix();
	public Paint pnt = new Paint();
	public Resources resources;
	public GameLoop loop;
	public int hang_d = 4,hang_m = 1;
	public ArrayList<Finger> fingers = new ArrayList<Finger>();
	public speng parent;
	public ArrayList<ScreenObject>[] object_layers;
	public int runtime = 0;
	public float[] upright = new float[]{0,0,0};
	public float[] tilt = new float[]{0,0,0};
	public float[] acce = new float[]{0,0,0};
	public boolean trailsOn = true;
	public int backgroundColor = 0x000000;
	public GameView(speng context) {
		super(context);
		parent = context;
		init();
	}
	public GameView(speng context,int screen_size_x,int screen_size_y) {
		super(context);
		parent = context;
		psz = new int[]{screen_size_x,screen_size_y};
		pixels = new int[psz[0]*psz[1]];
		init();
	}
	public void init(){
		resources = parent.getResources();
		setKeepScreenOn(true);
		upright = new float[]{acce[0],acce[1],acce[2]};
		camera_matrix.preScale((float)parent.dimensions[0]/psz[0], (float)parent.dimensions[1]/psz[1]);
		getHolder().addCallback(this);
		object_layers = new ArrayList[10];
		for (int i = 0;i<object_layers.length;i++){
			object_layers[i] = new ArrayList<ScreenObject>();
		}
		hud_objects = object_layers[0];
		game_objects = object_layers[2];
	}
	public void StartGame(){
		loop = new GameLoop(this,this.getHolder());
	}
	public void EnterFrame(){
		clear();
		Render();
	}
	public void NewAccelerometerValues(float x,float y,float z){
		tilt = new float[]{upright[0]-x,upright[1]-y,upright[2]-z};
		acce = new float[]{x,y,z};
	}
	public void Render(){
		runtime++;
		for (int i = object_layers.length-1;i>0;i--){
			for (int u = object_layers[i].size()-1;u>=0;u--){
				object_layers[i].get(u).Draw(this, cam);
			}
		}
		for (int i = hud_objects.size()-1;i>=0;i--){
			hud_objects.get(i).Draw(this,Satrix.identity);
		}
	}
	public void Draw(Canvas canvas){
		Bitmap bit = Bitmap.createBitmap(pixels,psz[0], psz[1],Bitmap.Config.RGB_565);
		canvas.drawBitmap(bit, camera_matrix, pnt);
	}
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		// TODO Auto-generated method stub
		
	}

	public void surfaceCreated(SurfaceHolder holder) {
		// TODO Auto-generated method stub
		
	}

	public void surfaceDestroyed(SurfaceHolder holder) {
		// TODO Auto-generated method stub
		
	}
	public int get(int x, int y) {
		if (x>=0&&x<psz[0]&&y>=0&&y<psz[1]){
		return pixels[x*psz[0] + y];
		}else{
			return 0;
		}
	}
	public void setpc(int x, int y, int color) {
		if (color!=1){
		pixels[y*psz[0] + x] = color;
		}
	}
	public void set(int x, int y, int color) {
		if (color!=1){
		if (x>=0&&x<psz[0]&&y>=0&&y<psz[1]){
		pixels[y*psz[0] + x] = color;
		}
		}
	}
	public int get(float x, float y) {
		x = (int)x;
		y = (int)y;
		if (x>=0&&x<psz[0]&&y>=0&&y<psz[1]){
		return pixels[(int)(y*psz[0] + x)];
		}else{
			return 0;
		}
	}
	public void set(float x, float y, int color) {
		if (color!=1){
		x = GameMath.round(x);
		y = GameMath.round(y);
		if (x>=0&&x<psz[0]&&y>=0&&y<psz[1]){
		pixels[(int)(y*psz[0] + x)] = color;
		}
		}
	}
	public void setpc(float x, float y, int color) {
		if (color!=1){
		x = (int)x;
		y = (int)y;
		pixels[(int)(y*psz[0] + x)] = color;
		}
	}
	public void alp(float x, float y, int color,int weight) {
		if (color!=1){
		x = (int)x;
		y = (int)y;
		final int wei = 256-weight;
		if (x>=0&&x<psz[0]&&y>=0&&y<psz[1]){
			final int before = pixels[(int)(y*psz[0] + x)];
			pixels[(int)(y*psz[0] + x)] = ((((color>>16) * weight + (before>>16)*wei)/256) <<16) | ((((color>>8&0xFF) *weight + (before>>8&0xFF) * wei)/256) << 8) | ((color&0xFF*weight) + (before&0xFF)*wei)/256;
		}
		}
	}
	public float chbx(float x) {
		if (x<0){
			return 0;
		}else if (x>=psz[0]){
			return psz[0]-1;
		}else {
			return x;
		}
	}
	public float chby(float y) {
		if (y<0){
			return 0;
		}else if (y>=psz[1]){
			return psz[1]-1;
		}else {
			return y;
		}
	}
	public int chbx(int x) {
		if (x<0){
			return 0;
		}else if (x>=psz[0]){
			return psz[0]-1;
		}else {
			return x;
		}
	}
	public int chby(int y) {
		if (y<0){
			return 0;
		}else if (y>=psz[1]){
			return psz[1]-1;
		}else {
			return y;
		}
	}
	public boolean checkBound(float x,float y){
		if (x>=0&&x<psz[0]&&y>=0&&y<psz[1]){
		return true;
		}else{
			return false;
		}
	}
	public boolean checkBound(int x,int y){
		if (x>=0&&x<psz[0]&&y>=0&&y<psz[1]){
		return true;
		}else{
			return false;
		}
	}
	public void add(ScreenObject object, int layer){
		object_layers[layer].add(object);
	}
	public void add(ScreenObject object){
		game_objects.add(object);
	}
	public void rmv(ScreenObject object){
		for (int i = object_layers.length-1;i>=0;i--){
			for (int u = object_layers[i].size()-1;u>=0;u--){
				if (object_layers[i].get(u) == object){
					object_layers[i].remove(u);
				}
			}
		}
	}
	public void clearStage(){
		for (int i = object_layers.length-1;i>=0;i--){
			for (int u = object_layers[i].size()-1;u>=0;u--){
					object_layers[i].remove(u);
			}
		}
	}
	public void clear(){
		if (trailsOn){
		for (int i = 0;i<pixels.length;i++){
			pixels[i] = (((pixels[i]>>16)/hang_d*hang_m)<<16) | (((pixels[i]>>8 & 0xFF)/hang_d*hang_m)<<8) | (((pixels[i] & 0xFF)/hang_d*hang_m));
		}
		}else{
			for (int i = 0;i<pixels.length;i++){
				pixels[i] =backgroundColor;
			}
		}
	}
	public Model modelFromImage(int id){
		Resources res = resources;
		Bitmap bit = BitmapFactory.decodeResource(res, id);
		int width = bit.getWidth();
		int height = bit.getHeight();
		int[] pixels = new int[width*height];
		for (int i = 0;i<width;i++){
			for (int u = 0;u<height;u++){
				int argb =  bit.getPixel(i, u);
				pixels[i * height + u] = argb & 0x00FFFFFF;
			}
		}
		ArrayList<Integer> colors = new ArrayList<Integer>();
		int[] inds = new int[pixels.length];
		for (int i = 0;i<inds.length;i++){
			int ind =colors.indexOf(pixels[i]); 
			if (ind==-1){
				colors.add(pixels[i]);
				inds[i] = colors.indexOf(pixels[i]);
			}else{
				inds[i] = ind;
			}
		}
		final int len = colors.size();
		int[] icolors = new int[len];
		for (int i = 0;i<len;i++){
			icolors[i] = colors.get(i);
		}
		return new Model(width,height,inds,icolors);
		
	}
	public boolean onTouchEvent(MotionEvent ev){
		final int action = ev.getAction();
		switch(action & MotionEvent.ACTION_MASK){
		case MotionEvent.ACTION_DOWN:{
			Log.d("GAME","FINGER DOWN AD");
			float x = ev.getX();
			float y = ev.getY();
			
			Finger fin = new Finger(x,y,x/parent.dimensions[0]*psz[0],y/parent.dimensions[1]*psz[1],GameMath.rand(0xFFFFFF));
			fingers.add(fin);
			break;
		}
		case MotionEvent.ACTION_POINTER_DOWN:{
			Log.d("GAME","FINGER DOWN APD");
			float x = ev.getX(1);
			float y = ev.getY(1);
			Finger fin = new Finger(x,y,x/parent.dimensions[0]*psz[0],y/parent.dimensions[1]*psz[1],GameMath.rand(0xFFFFFF));
			fingers.add(fin);
			break;
		}
		case MotionEvent.ACTION_MOVE:{
			for (int t = 0;t<ev.getPointerCount();t++){
			float x = ev.getX(t);
			float y = ev.getY(t);
			float mdis = 9999;
			int sel = 0;
			for (int i = fingers.size()-1;i>=0;i--){
				float a = fingers.get(i).screenx - x;
				float b = fingers.get(i).screeny - y;
				float c = GameMath.sqrt(a*a+b*b);
				if (c<mdis){
					mdis = c;
					sel = i;
				}
			}
			fingers.get(sel).screenx = x;
			fingers.get(sel).screeny = y;
			fingers.get(sel).x = x/parent.dimensions[0]*psz[0];
			fingers.get(sel).y = y/parent.dimensions[1]*psz[1];
			}
			break;
		}
		case MotionEvent.ACTION_UP: {
			Log.d("GAME","FINGER UP AD");
			float x = ev.getX();
			float y = ev.getY();
			float mdis = 9999;
			int sel = 0;
			for (int i = fingers.size()-1;i>=0;i--){
				float a = fingers.get(i).screenx - x;
				float b = fingers.get(i).screeny - y;
				float c = GameMath.sqrt(a*a+b*b);
				if (c<mdis){
					mdis = c;
					sel = i;
				}
			}
			fingers.remove(sel);
			break;
		}
		case MotionEvent.ACTION_POINTER_UP: {
			Log.d("GAME","FINGER UP APD");
			float x = ev.getX(1);
			float y = ev.getY(1);
			float mdis = 9999;
			int sel = 0;
			for (int i = fingers.size()-1;i>=0;i--){
				float a = fingers.get(i).screenx - x;
				float b = fingers.get(i).screeny - y;
				float c = GameMath.sqrt(a*a+b*b);
				if (c<mdis){
					mdis = c;
					sel = i;
				}
			}
			fingers.remove(sel);
			break;
		}
		}
		return true;
	}
	public void EndGame(){
		loop.running = false;
	}
}
